﻿#ifndef XQFTP_H
#define XQFTP_H
//#include"curl/curl.h"
#include<QObject>
#include"XQFtpInfo.h"
#include"XQFtpFileTransferInfo.h"
#include"XQFtpFileInfo.h"
#ifdef _DEBUG
#pragma comment(lib,"x64-Debug/libcurl-d_imp.lib")
#else
#pragma comment(lib,"x64-Release/libcurl_imp.lib")
#endif // _DEBUG
typedef void CURL;
using voidFunc = std::function<void()>;//无类型函数指针
#define NULLFUNC voidFunc()  //空函数
class XQFtp:public QObject
{
	Q_OBJECT
public:
	XQFtp(QObject* parent = nullptr);
	~XQFtp();
	//可以多线程上传文件
	template<typename _Progress, typename _Finish>
	static std::function<void()> UploadRunnable(XQFtp* ftp, bool autoDelete, _Finish FinishSlots = NULLFUNC, _Progress ProgressSlots = NULLFUNC);
	//可以多线程下载文件
	template<typename _Progress, typename _Finish>
	static std::function<void()> DownloadRunnable(XQFtp* ftp, bool autoDelete, _Finish FinishSlots = NULLFUNC, _Progress ProgressSlots = NULLFUNC);
	//可以多线程获取远程目录
	template<typename _Finish>
	static std::function<void()> fileListRunnable(XQFtp* ftp, bool autoDelete, _Finish FinishSlots = NULLFUNC);
	//拷贝一个ftp
	XQFtp* copy(QObject* parent = nullptr);
public slots:
	void setHost(const QString& host, const unsigned short int port=21);
	void login(const QString& username, const QString& password);
	//设置远程主机的目录
	void setRemoteFileDir(const QString& dir);
	//进入目录
	void cd(const QString& dir);
	//获取文件列表信息
	QList<XQFtrFileInfo> fileList(const QString& path="", const bool updataPath = false);
	//获取服务器上的文件大小
	size_t fileSize(const QString& remote_file_path);
	//拷贝文件
	void copy(const QString& source, const QString& newPath);
	//创建目录
	int mkdir(const QString& path);
	//递归创建路径
	int mkpath(const QString& path);
	//删除文件或非空目录
	int remove(const QString& path);
	//删除文件或目录递归方式删除全部慎用
	int removeDir(const QString& path);
	//重命名
	int rename(const QString& path,const QString& newName);
	//设置上传或下载的路径
	void setPath(const QString& local_file_path, const QString& remote_file_path);
	//上传
	int Upload(const QString& local_file_path, const QString& remote_file_path);
	int Upload();
	//下载
	int Download(const QString& local_file_path, const QString& remote_file_path);
	int Download();
signals://信号
	//上传/下载开始信号
	void start(const XQFtpFileTransferInfo& info);
	//上传/下载进度信号
	void progress(const XQFtpFileTransferInfo& info);
	//上传/下载完成信号
	void finish(const XQFtpFileTransferInfo& info);
	//列表获取完成返回信号
	void fileListFinish(QList<XQFtrFileInfo> info);
protected:
	CURL* init();
	QString setUrl(QString path = "", const bool updataPath = false);
	//ftp命令发送
	int slotFTPCMDExec(const QString& CMD, const QString& path = "", const bool updataPath = false);
protected:
	XQFtpInfo m_ftpInfo;//ftp服务器的信息
	QString m_remote_file_dir;//远程的文件目录
	qint64 m_timeout=3;//超时时间
	QString m_local_file_path;//本地文件路径
	QString m_remote_file_path;//远程文件路径
};
// 解析Content-Length头
size_t getContentLengthFunc(void* ptr, size_t size, size_t nmemb, void* stream);


template<typename _Progress, typename _Finish>
inline std::function<void()> XQFtp::UploadRunnable(XQFtp* ftp, bool autoDelete, _Finish FinishSlots, _Progress ProgressSlots)
{
	auto func = [=] {
		//判断是否绑定槽函数
		if (FinishSlots != NULL)
			connect(ftp, &XQFtp::finish, FinishSlots);
		if (ProgressSlots != NULL)
			connect(ftp, &XQFtp::progress, ProgressSlots);
		ftp->Upload();
		if(autoDelete)//运行完毕是否清理
		 ftp->deleteLater();
	};
	return func;
}

template<typename _Progress, typename _Finish>
inline std::function<void()> XQFtp::DownloadRunnable(XQFtp* ftp, bool autoDelete, _Finish FinishSlots, _Progress ProgressSlots)
{
	auto func = [=] {
		//判断是否绑定槽函数
		if (FinishSlots != NULL)
			connect(ftp, &XQFtp::finish, FinishSlots);
		if (ProgressSlots != NULL)
			connect(ftp, &XQFtp::progress, ProgressSlots);
		ftp->Download();
		if (autoDelete)//运行完毕是否清理
			ftp->deleteLater();
	};
	return func;
}

template<typename _Finish>
inline std::function<void()> XQFtp::fileListRunnable(XQFtp* ftp, bool autoDelete, _Finish FinishSlots)
{
	auto func = [=] {
		//判断是否绑定槽函数
		if (FinishSlots != NULL)
			connect(ftp, &XQFtp::fileListFinish, FinishSlots);
		ftp->fileList();
		if (autoDelete)//运行完毕是否清理
			ftp->deleteLater();
	};
	return func;
}
#endif // !ftp